/*
 * Copyright 2022-2027 中国信息通信研究院云计算与大数据研究所
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package com.service.impl;

import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import com.common.calculation.InitiUtil;
import com.common.calculation.NameUtil;
import com.common.calculation.TimeUtil;
import com.common.constant.AccountConstant;
import com.common.constant.InitialDataConstant;
import com.common.constant.ParamConstant;
import com.common.constant.ProcessConstant;
import com.localMapper.ParamcfgMapper;
import com.localMapper.ProcessListMapper;
import com.mapper.InitialData;
import com.mapper.ReadDataConfig;
import com.pojo.Account;
import com.pojo.Branch;
import com.pojo.Customer;
import com.pojo.DataConfig;
import com.pojo.Paramcfg;
import com.pojo.ProcessList;
import com.pojo.Salarylist;
import com.pojo.Sjno;
import com.service.InitialDataService;

@Service
@Scope("prototype")
public class InitialDataServiceImpl implements InitialDataService,Runnable {

    private final Logger logger = LoggerFactory.getLogger(InitialDataServiceImpl.class); 

    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    @Autowired
    private ProcessListMapper processListMapper;
    private StringBuffer buf = new StringBuffer();
    @Autowired
    private InitialData initialData;

    @Autowired
    private ReadDataConfig readDataCfg;

    @Autowired
    private ParamcfgMapper paramcfgMapper;
    
    private String datacfg_id;
    private String process_id;
    static Integer datacfg_sjnonum;
    static Integer datacfg_brhnum;
    static Integer datacfg_accnum;
    static Integer datacfg_cusnum;
    static Integer pageSize;
    
    private List<String> initResultList = new ArrayList<String>();

	@Override
	public void run() {
    	initialData(datacfg_id);
	}
	
    @Override
    public void initialData(String dataconfig_id) {
    	Integer branchCount = initialData.countBranch();
        long now = System.currentTimeMillis();
    	if(branchCount!=null&&branchCount>0) {
            buf.append("数据已经初始化,请手动删除数据。");
            insertProcessList(100);
            System.out.println(" 数据已经初始化过,请手动删除数据。");
            System.out.println(String.format(" 数据初始化结束，总耗时 %s", TimeUtil.formatDuration(System.currentTimeMillis()-now)));
    		return;
    	}
        DataConfig df = readDataCfg.readDataCfg(dataconfig_id);
        datacfg_sjnonum = df.getDatacfg_sjnonum();
        datacfg_brhnum = df.getDatacfg_brhnum();
        datacfg_accnum = df.getDatacfg_accnum();
        datacfg_cusnum = df.getDatacfg_cusnum();
        Paramcfg paramcfg = paramcfgMapper.getParamByName(ParamConstant.PARAM_INIT_PAGE);
        pageSize = Integer.parseInt(paramcfg.getParam_value());
        buf.append("<font color=\"#409EFF\">初始化数据开始</font>");
        buf.append("<br/>");
        insertProcessList(1);
        initBranch();//初始化网点
        insertProcessList(5);
        initSjno();//初始化科目
        insertProcessList(10);
        initCustomer(initialData);//初始化公司客户
        insertProcessList(30);
        boolean isSuccess = initAccount(initialData);//初始化账户
        if(!isSuccess) {
        	buf = new StringBuffer();
        	buf.append("数据初始化失败，查本地库paramcfg表中init_page_size参数过大，请进行合理调整，并重新建立数据库。");
            insertProcessList(100);
            System.out.println(" 数据初始化失败，请检查本地库paramcfg表中init_page_size参数过大，并重新建立数据库。");
            return;
        }
        initCompanyAccount();//初始化代发工资账户
        initAtomicityCommitAccount();//初始化原子性账户
        initAtomicityUnCommitAccount();//初始化原子性账户
        initIsolationAccount();//初始化隔离性资账户
        insertProcessList(50);
        initSalary();//初始化工资单
        insertProcessList(55);
        updateSjnoBale();//汇总科目余额
        insertProcessList(70);
        updateCusBale();//汇总客户资产余额
        initResultList.add(String.format(" 数据初始化结束，总耗时 %s", TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<font color=\"#409EFF\">"+String.format(" 数据初始化结束，总耗时 %s", TimeUtil.formatDuration(System.currentTimeMillis()-now))+"</font>");
        buf.append("<br/>");
    	insertProcessList(100);
        initResultList.forEach(System.out::println);
    }

    private void insertProcessList(int process_perc) {
		ProcessList processList = new ProcessList();
		processList.setDatacfg_id(datacfg_id);
		processList.setProcess_id(process_id);
		processList.setProcess_type(ProcessConstant.PROCESS_INIT);
		processList.setProcess_content(buf.toString());
		processList.setProcess_time(new Timestamp(System.currentTimeMillis()));
		processList.setProcess_perc(process_perc);
		processListMapper.insertProcessList(processList);
	}
    
    
    /**
     * 初始化隔离性账户
     */
    private void initIsolationAccount() {
    	logger.info(" InitialDataServiceImpl initIsolationAccount begin ");
    	long now = System.currentTimeMillis();
    	//添加公司账户
        ArrayList<Account> acs = new ArrayList<>();
        for (int i = 1; i <= AccountConstant.ACCOUNT_DEFAULT_NUM; i++) {
            Account a = new Account();
            a.setAccount_id("90"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
            Random r = new Random();
            a.setAccount_sjnoid(String.format("%05d",(r.nextInt(datacfg_sjnonum )+1)));
            a.setAccount_stat("0");
            a.setAccount_custid("1111111111");
            a.setAccount_bale(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_pswd("0000000000000000");
            a.setAccount_name(NameUtil.getName());
            a.setAccount_amrz(0.0F);
            a.setAccount_inmod("a");
            a.setAccount_itrz(0.0F);
            a.setAccount_branchid(String.valueOf(r.nextInt(datacfg_brhnum )+1+ InitiUtil.getBrhnum(datacfg_brhnum)));
            a.setAccount_mdate(new Date());
            a.setAccount_mtime(new Time(System.currentTimeMillis()));
            a.setAccount_fld1(InitiUtil.getRandomString(150));
            a.setAccount_fld2(InitiUtil.getRandomString(150));
            a.setAccount_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            acs.add(a);
        }
        List<List<Account>> list = splitAccount(acs,pageSize);
        for(List<Account> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                initialData.insertAccount(temp);
            	dataSourceTransactionManager.commit(transactionStatus);//提交
    		} catch (Exception e) {
    			e.printStackTrace();
    	    	logger.error(" InitialDataServiceImpl initIsolationAccount error {} ",e);
    	    	dataSourceTransactionManager.rollback(transactionStatus);
    		}
        }
    	logger.info(" InitialDataServiceImpl initIsolationAccount end size {} cost time {} ",20,System.currentTimeMillis()-now);
				
	}
    /**
     * 初始化原子性账户
     */
	private void initAtomicityCommitAccount() {
		logger.info(" InitialDataServiceImpl initAtomicityCommitAccount begin ");
    	long now = System.currentTimeMillis();
    	ArrayList<Account> acs = new ArrayList<>();
        for (int i = 1; i <= AccountConstant.ACCOUNT_DEFAULT_NUM; i++) {
            Account a = new Account();
            a.setAccount_id("80"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
            Random r = new Random();
            a.setAccount_sjnoid(String.format("%05d",(r.nextInt(datacfg_sjnonum )+1)));
            a.setAccount_stat("0");
            a.setAccount_custid("1111111111");
            a.setAccount_bale(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_pswd("0000000000000000");
            a.setAccount_name(NameUtil.getName());
            a.setAccount_amrz(0.0F);
            a.setAccount_inmod("a");
            a.setAccount_itrz(0.0F);
            a.setAccount_branchid(String.valueOf(r.nextInt(datacfg_brhnum )+1+ InitiUtil.getBrhnum(datacfg_brhnum)));
            a.setAccount_mdate(new Date());
            a.setAccount_mtime(new Time(System.currentTimeMillis()));
            a.setAccount_fld1(InitiUtil.getRandomString(150));
            a.setAccount_fld2(InitiUtil.getRandomString(150));
            a.setAccount_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            acs.add(a);
        }
        List<List<Account>> list = splitAccount(acs,pageSize);
        for(List<Account> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                initialData.insertAccount(temp);
            	dataSourceTransactionManager.commit(transactionStatus);//提交
    		} catch (Exception e) {
    			e.printStackTrace();
    	    	logger.error(" InitialDataServiceImpl initAtomicityCommitAccount error {} ",e);
    	    	dataSourceTransactionManager.rollback(transactionStatus);
    		}
        	
        }
    	logger.info(" InitialDataServiceImpl initAtomicityCommitAccount end size {} cost time {} ",20,System.currentTimeMillis()-now);
		
	}

	
	 /**
     * 初始化原子性账户
     */
	private void initAtomicityUnCommitAccount() {
		logger.info(" InitialDataServiceImpl initAtomicityUnCommitAccount begin ");
    	long now = System.currentTimeMillis();
    	 ArrayList<Account> acs = new ArrayList<>();
         for (int i = 1; i <= AccountConstant.ACCOUNT_DEFAULT_NUM; i++) {
             Account a = new Account();
             a.setAccount_id("81"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
             Random r = new Random();
             a.setAccount_sjnoid(String.format("%05d",(r.nextInt(datacfg_sjnonum )+1)));
             a.setAccount_stat("0");
             a.setAccount_custid("1111111111");
             a.setAccount_bale(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
             a.setAccount_pswd("0000000000000000");
             a.setAccount_name(NameUtil.getName());
             a.setAccount_amrz(0.0F);
             a.setAccount_inmod("a");
             a.setAccount_itrz(0.0F);
             a.setAccount_branchid(String.valueOf(r.nextInt(datacfg_brhnum )+1+ InitiUtil.getBrhnum(datacfg_brhnum)));
             a.setAccount_mdate(new Date());
             a.setAccount_mtime(new Time(System.currentTimeMillis()));
             a.setAccount_fld1(InitiUtil.getRandomString(150));
             a.setAccount_fld2(InitiUtil.getRandomString(150));
             a.setAccount_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
             a.setAccount_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
             acs.add(a);
         }
         List<List<Account>> list = splitAccount(acs,pageSize);
         for(List<Account> temp : list) {
        	 TransactionStatus transactionStatus = null;
         	try {
         		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                initialData.insertAccount(temp);
             	dataSourceTransactionManager.commit(transactionStatus);//提交
     		} catch (Exception e) {
     			e.printStackTrace();
     	    	logger.error(" InitialDataServiceImpl initAtomicityUnCommitAccount error {} ",e);
     	    	dataSourceTransactionManager.rollback(transactionStatus);
     		}
        	 
         }
    	logger.info(" InitialDataServiceImpl initAtomicityUnCommitAccount end size {} cost time {} ",20,System.currentTimeMillis()-now);
		
	}
	
	
	/**
     * 汇总科目下余额
     */
    private void updateSjnoBale() {
        logger.info(" InitialDataServiceImpl updateSjnoBale begin ");
        long now = System.currentTimeMillis();
    	TransactionStatus transactionStatus = null;
    	try {
    		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    		initialData.updateSjnoBale();
        	dataSourceTransactionManager.commit(transactionStatus);//提交
		} catch (Exception e) {
			e.printStackTrace();
	    	logger.error(" InitialDataServiceImpl updateSjnoBale error {} ",e);
	    	dataSourceTransactionManager.rollback(transactionStatus);
		}
        logger.info(" InitialDataServiceImpl updateSjnoAndCusBale  cost time {} ",System.currentTimeMillis()-now);
        initResultList.add(String.format(" 更新汇总科目余额，耗时 %s",TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 更新汇总科目余额，耗时 %s",TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
    }

    /**
     * 汇总客户资产余额
     */
    private void updateCusBale() {
        logger.info(" InitialDataServiceImpl updateCusBale begin ");
        long now = System.currentTimeMillis();
        Paramcfg paramcfg = paramcfgMapper.getParamByName(ParamConstant.PARAM_UPDATE_CUSTOMER);
        int size = Integer.parseInt(paramcfg.getParam_value());
        int mod = datacfg_cusnum%size;
        int page = datacfg_cusnum/size;
        if(mod!=0) {
        	page = page + 1;
        }
        for (int i = 0; i < page; i++) {
        	TransactionStatus transactionStatus = null;
            try {
                transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                if(i+1==page&&mod>0) {
                    initialData.updateCustomerBale(i*size,mod);
                }else {
                    initialData.updateCustomerBale(i*size,size);
                }
                dataSourceTransactionManager.commit(transactionStatus);//提交
            } catch (Exception e) {
    			e.printStackTrace();
                logger.error(" InitialDataServiceImpl updateCusBale error {} ",e);
                dataSourceTransactionManager.rollback(transactionStatus);
            }
		}
        logger.info(" InitialDataServiceImpl updateCusBale  cost time {} ",System.currentTimeMillis()-now);
        initResultList.add(String.format(" 更新汇总客户资产余额，耗时 %s",TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 更新汇总客户资产余额，耗时 %s",TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
    }

	/**
     * 初始化代发工资单
     */
    private void initSalary() {
    	long now = System.currentTimeMillis();
    	 ArrayList<Salarylist> sas = new ArrayList<>();
    	 String branchId = "";
         for (int i = 1 ; i <= datacfg_brhnum/4 ; i++) {
        	 if((i-1)%2==0) {
        		 branchId = String.valueOf(i*4+InitiUtil.getBrhnum(datacfg_brhnum));
        	 }
             Salarylist sal = new Salarylist();
             sal.setSalarylist_branchid(branchId);
             sal.setSalarylist_accountid("60"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+(new Random().nextInt(datacfg_accnum)+1)));
             sal.setSalarylist_bale(BigDecimal.valueOf(1000.00));
             sal.setSalarylist_fld1(InitiUtil.getRandomString(150));
             sal.setSalarylist_fld2(InitiUtil.getRandomString(150));
             sal.setSalarylist_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
             sal.setSalarylist_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
             sas.add(sal);
         }
    	
        List<List<Salarylist>> list = splitSalarylist(sas,pageSize);
        for(List<Salarylist> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        		 //工资单
                initialData.insertSalaryList(temp);
            	dataSourceTransactionManager.commit(transactionStatus);//提交
    		} catch (Exception e) {
    			e.printStackTrace();
    	    	logger.error(" InitialDataServiceImpl initSalary error {} ",e);
    	    	dataSourceTransactionManager.rollback(transactionStatus);
    		}
        }
        initResultList.add(String.format(" 初始化salarylist（代发工资）表，记录数 %s ，耗时 %s",datacfg_brhnum/4,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 初始化salarylist（代发工资）表，记录数 %s ，耗时 %s",datacfg_brhnum/4,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
	}

    /**
     * 初始化代发工资账户
     */
	private void initCompanyAccount() {
    	logger.info(" InitialDataServiceImpl initCompanyAccount begin ");
    	long now = System.currentTimeMillis();
    	//添加公司账户
        ArrayList<Account> acs = new ArrayList<>();
        for (int i = 1; i <= datacfg_brhnum; i++) {
            Account a = new Account();
            a.setAccount_id("70"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
            Random r = new Random();
            a.setAccount_sjnoid(String.format("%05d",(r.nextInt(datacfg_sjnonum )+1)));
            a.setAccount_stat("0");
            a.setAccount_custid(String.valueOf(InitiUtil.getCusnum(datacfg_cusnum)+(r.nextInt(datacfg_cusnum)+1)));
            a.setAccount_bale(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_pswd("0000000000000000");
            a.setAccount_name(NameUtil.getName());
            a.setAccount_amrz(0.0F);
            a.setAccount_inmod("a");
            a.setAccount_itrz(0.0F);
            a.setAccount_branchid(String.valueOf(InitiUtil.getBrhnum(datacfg_brhnum) + i));
            a.setAccount_mdate(new Date());
            a.setAccount_mtime(new Time(System.currentTimeMillis()));
            a.setAccount_fld1(InitiUtil.getRandomString(150));
            a.setAccount_fld2(InitiUtil.getRandomString(150));
            a.setAccount_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            a.setAccount_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            acs.add(a);
        }
        List<List<Account>> list = splitAccount(acs,pageSize);
        for(List<Account> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        		
                initialData.insertAccount(temp);
            	dataSourceTransactionManager.commit(transactionStatus);//提交
    		} catch (Exception e) {
    	    	logger.error(" InitialDataServiceImpl initCompanyAccount error {} ",e);
    	    	dataSourceTransactionManager.rollback(transactionStatus);
    		}
        	
        }
    	logger.info(" InitialDataServiceImpl initCompanyAccount end size {} cost time {} ",datacfg_brhnum,System.currentTimeMillis()-now);
	}


	/**
     * 初始化话账户
     * @param initialData
     */
    private boolean initAccount(InitialData initialData) {
    	logger.info(" InitialDataServiceImpl initAccount begin ");
    	long now = System.currentTimeMillis();
    	try {
    		ForkJoinPool pool = new ForkJoinPool();
	        //添加个人账户
    		ForkJoinTask<Integer> task = pool.submit(new ParallelExecuteAddAccountTask(initialData,1,datacfg_accnum));
    		task.get();
	        pool.shutdown();
	        //阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
	        pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
	        // 关闭线程池
		} catch (Exception e) {
	    	logger.error(" InitialDataServiceImpl initAccount error {} ",e);
			return false;
		}
    	logger.info(" InitialDataServiceImpl initAccount end  size {} cost time {} ",datacfg_accnum,System.currentTimeMillis()-now);
        initResultList.add(String.format(" 初始化account（账户）表，记录数 %s ，耗时 %s",datacfg_accnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 初始化account（账户）表，记录数 %s ，耗时 %s",datacfg_accnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
        return true;
    }

	/**
     * 初始化公司客户
     * @param initialData
     */
    private void initCustomer(InitialData initialData) {
    	long now = System.currentTimeMillis();
    	logger.info(" InitialDataServiceImpl initCustomer begin ");
    	try {
    		ForkJoinPool pool = new ForkJoinPool();
            //添加客户
    		ForkJoinTask<Integer> task = pool.submit(new ParallelExecuteAddCustomerTask(initialData,1,datacfg_cusnum));
    		task.get();
            pool.shutdown();
    		//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            // 关闭线程池
		} catch (Exception e) {
	    	logger.error(" InitialDataServiceImpl initCustomer error {} ",e);
		}
    	logger.info(" InitialDataServiceImpl initCustomer end  size {} cost time {} ",datacfg_cusnum,System.currentTimeMillis()-now);
        initResultList.add(String.format(" 初始化customer（客户）表，记录数 %s ，耗时 %s",datacfg_cusnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 初始化customer（客户）表，记录数 %s ，耗时 %s",datacfg_cusnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
    }


	/**
     * 初始化科目数
     */
    private void initSjno() {
    	logger.info(" InitialDataServiceImpl initSjno begin ");
    	long now = System.currentTimeMillis();
        ArrayList<Sjno> sjnos = new ArrayList<>();
        for (int i = 1; i <= datacfg_brhnum; i++) {
            for (int j = 1; j <= datacfg_sjnonum; j++) {
                Sjno sj = new Sjno();
                sj.setSjno_id(String.format("%05d",j)); //科目id
                sj.setSjno_branchid(String.valueOf(InitiUtil.getBrhnum(datacfg_brhnum) + i));//网点id
                sj.setSjno_name("科目"+j);
                sj.setSjno_fld1(InitiUtil.getRandomString(150));
                sj.setSjno_fld2(InitiUtil.getRandomString(150));
                sj.setSjno_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                sj.setSjno_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                sjnos.add(sj);
            }
        }
        List<List<Sjno>> list = splitList(sjnos,pageSize);
        for(List<Sjno> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        		initialData.insertSjno(temp);
            	dataSourceTransactionManager.commit(transactionStatus);//提交
			} catch (Exception e) {
				e.printStackTrace();
		    	dataSourceTransactionManager.rollback(transactionStatus);
			}
        }
    	logger.info(" InitialDataServiceImpl initSjno end size {} cost time {} ",datacfg_brhnum*datacfg_sjnonum,System.currentTimeMillis()-now);
        initResultList.add(String.format(" 初始化sjno（科目）表，记录数 %s ，耗时 %s",datacfg_brhnum*datacfg_sjnonum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 初始化sjno（科目）表，记录数 %s ，耗时 %s",datacfg_brhnum*datacfg_sjnonum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
    }

    public List<List<Sjno>> splitList(List<Sjno> list, int len) {
        
        if (list == null || list.isEmpty() || len < 1) {
            return Collections.emptyList();
        }

        List<List<Sjno>> result = new ArrayList<>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<Sjno> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }
    
    public List<List<Branch>> splitBranch(List<Branch> list, int len) {
        
        if (list == null || list.isEmpty() || len < 1) {
            return Collections.emptyList();
        }

        List<List<Branch>> result = new ArrayList<>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<Branch> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }
    public List<List<Salarylist>> splitSalarylist(List<Salarylist> list, int len) {
        
        if (list == null || list.isEmpty() || len < 1) {
            return Collections.emptyList();
        }

        List<List<Salarylist>> result = new ArrayList<>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<Salarylist> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }
    
 public List<List<Account>> splitAccount(List<Account> list, int len) {
        
        if (list == null || list.isEmpty() || len < 1) {
            return Collections.emptyList();
        }

        List<List<Account>> result = new ArrayList<>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<Account> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }
    
	/**
     * 初始化网点
     */
    private void initBranch() {
    	logger.info(" InitialDataServiceImpl initBranch begin ");
    	long now = System.currentTimeMillis();
    	//网点数
        List<Branch> branches = new ArrayList<>();
        for (int i = 1; i <= datacfg_brhnum; i++) {
            Branch br = new Branch();
            br.setBranch_id(String.valueOf(InitiUtil.getBrhnum(datacfg_brhnum) + i));//网点id
            br.setBranch_seq(1);
            br.setBranch_dacno("70"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
            br.setBranch_add(InitialDataConstant.INITIALIZATION_ADDRESS);
            br.setBranch_tel(InitialDataConstant.INITIALIZATION_PHONE);
            br.setBranch_fld1(InitiUtil.getRandomString(150));
            br.setBranch_fld2(InitiUtil.getRandomString(150));
            br.setBranch_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            br.setBranch_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
            branches.add(br);
        }
        List<List<Branch>> list = splitBranch(branches,pageSize);
        for(List<Branch> temp : list) {
        	TransactionStatus transactionStatus = null;
        	try {
        		transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                initialData.insertBranch(temp);		
            	dataSourceTransactionManager.commit(transactionStatus);//提交
    		} catch (Exception e) {
    			e.printStackTrace();
    	    	dataSourceTransactionManager.rollback(transactionStatus);
    		}
        }
    	logger.info(" InitialDataServiceImpl initBranch end size {} cost time {} ",datacfg_brhnum,System.currentTimeMillis()-now);
        initResultList.add(String.format(" 初始化branch（网点）表，记录数 %s ，耗时 %s",datacfg_brhnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append(String.format(" 初始化branch（网点）表，记录数 %s ，耗时 %s",datacfg_brhnum,TimeUtil.formatDuration(System.currentTimeMillis()-now)));
        buf.append("<br/>");
    }



	static class ParallelExecuteAddAccountTask extends RecursiveTask<Integer> {
		private static final long serialVersionUID = 1L;
        private static Random r = new  Random();
        private static Random r2 = new  Random();
        private final Logger logger = LoggerFactory.getLogger(InitialDataServiceImpl.class); 
        private InitialData initialData;
        private Integer startValue;
        private Integer endValue;
        
        public ParallelExecuteAddAccountTask(InitialData initialData, Integer startValue , Integer endValue) {
            this.initialData = initialData;
            this.startValue = startValue;
            this.endValue = endValue;
        }

        @Override
        protected Integer compute() {

            if(endValue - startValue < pageSize) {
            	logger.info(" InitialDataServiceImpl ParallelExecuteAddAccountTask compute startValue {} endValue {} ",startValue,endValue);
                try {
                	ArrayList<Account> accounts = new ArrayList<>();
                    for (int i = startValue; i <= endValue; i++) {
                        Account ac = new Account();
                        ac.setAccount_id("60"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+i));
                        ac.setAccount_sjnoid(String.format("%05d",(r.nextInt(datacfg_sjnonum )+1)));
                        ac.setAccount_stat(r2.nextInt(10) == 1 ? "1" : "0");
                        ac.setAccount_custid(String.valueOf(InitiUtil.getCusnum(datacfg_cusnum)+(r.nextInt(datacfg_cusnum)+1)));
                        ac.setAccount_bale(BigDecimal.valueOf(ac.getAccount_stat().equals("0") ? 88888888.88 : 0));
                        ac.setAccount_pswd("0000000000000000");
                        ac.setAccount_name(NameUtil.getName());
                        ac.setAccount_amrz(0.0F);
                        ac.setAccount_inmod("a");
                        ac.setAccount_itrz(0.0F);
                        ac.setAccount_branchid(String.valueOf(r.nextInt(datacfg_brhnum )+1+ InitiUtil.getBrhnum(datacfg_brhnum)));
                        ac.setAccount_mdate(new Date());
                        ac.setAccount_mtime(new Time(System.currentTimeMillis()));
                        ac.setAccount_fld1(InitiUtil.getRandomString(150));
                        ac.setAccount_fld2(InitiUtil.getRandomString(150));
                        ac.setAccount_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                        ac.setAccount_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                        accounts.add(ac);
                    }
                    initialData.insertAccount(accounts);
				} catch (Exception e) {
					e.printStackTrace();
	            	logger.error(" InitialDataServiceImpl ParallelExecuteAddAccountTask compute exception {} ",e);
	            	throw e;
				}
                return startValue;
            }
            else {
                ParallelExecuteAddAccountTask subTask1 = new ParallelExecuteAddAccountTask(initialData, startValue, startValue + pageSize - 1);
                subTask1.fork();
                ParallelExecuteAddAccountTask subTask2 = new ParallelExecuteAddAccountTask(initialData, startValue + pageSize, endValue);
                subTask2.fork();
                return startValue;
            }
        }
    }


    static class ParallelExecuteAddCustomerTask extends RecursiveTask<Integer> {

		private static final long serialVersionUID = 1L;

        private final Logger logger = LoggerFactory.getLogger(InitialDataServiceImpl.class); 

        private InitialData initialData;

        private Integer startValue;

        private Integer endValue;

        public ParallelExecuteAddCustomerTask(InitialData initialData, Integer startValue , Integer endValue) {
            this.initialData = initialData;
            this.startValue = startValue;
            this.endValue = endValue;
        }

        @Override
        protected Integer compute() {
            if(endValue - startValue < pageSize) {
                ArrayList<Customer> customers = new ArrayList<>();
            	logger.info(" InitialDataServiceImpl ParallelExecuteAddCustomerTask compute startValue {} endValue {} ",startValue,endValue);
            	try {
            		   for (int i = startValue; i <= endValue; i++) {
                           Customer cu = new Customer();
                           cu.setCustomer_id(String.valueOf(InitiUtil.getCusnum(datacfg_cusnum) + i));
                           cu.setCustomer_idtype("1");
                           cu.setCustomer_idno(InitiUtil.getRandomID());
                           cu.setCustomer_name(NameUtil.getName());
                           cu.setCustomer_add(InitialDataConstant.INITIALIZATION_ADDRESS);
                           cu.setCustomer_birthday(new Date());
                           cu.setCustomer_tel(InitiUtil.getTel());
                           cu.setCustomer_cdate(new Date());
                           cu.setCustomer_cbrhid(String.valueOf(InitiUtil.getBrhnum(datacfg_brhnum) + 1));
                           cu.setCustomer_bale(BigDecimal.valueOf(0.0));
                           cu.setCustomer_mdate(new Date());
                           cu.setCustomer_mtime(new Time(System.currentTimeMillis()));
                           cu.setCustomer_fld1(InitiUtil.getRandomString(150));
                           cu.setCustomer_fld2(InitiUtil.getRandomString(150));
                           cu.setCustomer_fld3(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                           cu.setCustomer_fld4(AccountConstant.ACCOUNT_BIGDECIMAL_MONERY);
                           customers.add(cu);
                       }
                       initialData.insertCustomer(customers);
				} catch (Exception e) {
					e.printStackTrace();
					throw e;
				}
                return startValue;
            }
            else {
            	ParallelExecuteAddCustomerTask subTask1 = new ParallelExecuteAddCustomerTask(initialData, startValue, startValue + pageSize - 1);
            	subTask1.fork();
            	ParallelExecuteAddCustomerTask subTask2 = new ParallelExecuteAddCustomerTask(initialData, startValue + pageSize, endValue);
            	subTask2.fork();

                return startValue;
            }
        }
    }


	public String getDatacfg_id() {
		return datacfg_id;
	}

	public void setDatacfg_id(String datacfg_id) {
		this.datacfg_id = datacfg_id;
	}
    
	public String getProcess_id() {
		return process_id;
	}

	public void setProcess_id(String process_id) {
		this.process_id = process_id;
	}

	
}
